package com.icycandy.blogmover.hi2wp;

import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

/**
 * 
 * @author icycandy
 */
public class HI2WP
{
	private ArrayList<Diary> blog = new ArrayList<Diary>();
	private final String baiduHi = "http://hi.baidu.com";
	private String blogUrl;
	private String nextUrl;
	private int diaryId = 0;
	private int commentId = 0;
	private HashSet<String> categories = new HashSet<String>();
	HtmlCleaner cleaner = null;
	
	public HI2WP(String blogName)
	{
		this.blogUrl = this.baiduHi + "/" + blogName + "/blog";
		
		this.diaryId = 0;
		this.commentId = 0;
		this.nextUrl = null;
		
		this.cleaner = new HtmlCleaner();
		//CleanerProperties properties = cleaner.getProperties();
	}
	
	public String getFirstUrl()
	{
		HtmlCleaner cleaner = new HtmlCleaner();
		TagNode node = null;
		String firstUrl = null;
		
		try
		{
			node = cleaner.clean(new URL(blogUrl), "gb2312");
			TagNode blogList = node.findElementByAttValue("id", "m_blog", true, true);
			TagNode firstBlog = blogList.findElementByAttValue("class", "tit", true, true);
			firstUrl = firstBlog.findElementByName("a", false).getAttributeByName("href");
		}
		catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		
		//System.out.println(firstUrl);
		
		return firstUrl;
	}
	
	public Diary getDiary(String url)
	{
		System.out.println(url);
		try
		{
			TagNode rootNode = this.cleaner.clean(new URL(url), "gb2312");
			TagNode blogNode = rootNode.findElementByAttValue("id", "m_blog", true, true);
			
			//提取标题
			TagNode titleNode = blogNode.findElementByAttValue("class", "tit", true, true);
			String title = titleNode.getText().toString();
			System.out.println(title);
			
			//提取日期
			TagNode dateNode = blogNode.findElementByAttValue("class", "date", true, true);
			String date = formatDate(dateNode.getText().toString());
			System.out.println(date);
			
			//提取正文
			TagNode contentNode = blogNode.findElementByAttValue("id", "blog_text", true, true);
			String content = contentNode.getText().toString();
			//System.out.println(content);
			
			TagNode optNode = blogNode.findElementByAttValue("class", "opt", true, true);
			
			//提取下一篇日志的url
			Pattern pattern = Pattern.compile("var.*pre.*=.*\\[(.*),.*,.*,'(.*)']");
			Matcher matcher = pattern.matcher(optNode.getText());
			if (matcher.find() && matcher.group(1).equals("true")) nextUrl = matcher.group(2);
			else nextUrl = null;
			//System.out.println(nextUrl);
			
			//提取文章分类
			TagNode categoryNode = optNode.findElementByAttValue("title", "查看该分类中所有文章", true, true);
			String category = categoryNode.getText().toString().replaceAll("类别：", "");
			System.out.println(category);
			
			//提取评论列表
			TagNode commentsNode = blogNode.findElementByAttValue("id", "in_comment", true, true);
			ArrayList<Comment> comments = getComments(commentsNode);
			
			if (null != comments) System.out.println("评论数" + comments.size());
			else System.out.println("评论数 0");
			
			//更新分类集合
			this.categories.add(category);
			
			return new Diary(this.diaryId++, date, title, content, category, comments);
		}
		catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	public ArrayList<Comment> getComments(TagNode commentsNode)
	{
		@SuppressWarnings("unchecked")
		List<TagNode> list = commentsNode.getElementListByAttValue("class", "item", true, true);
		if (list == null || list.size() == 0) return null;
		
		ArrayList<Comment> comments = new ArrayList<Comment>();
		for (TagNode node : list)
		{
			comments.add(getComment(node));
			//System.out.println(node.getText());
		}
		
		return comments;
	}
	
	private Comment getComment(TagNode commentNode)
	{
		TagNode userNode = commentNode.findElementByAttValue("class", "user", true, true);
		String regex = "writecmt\\(.*?,.*?,\"(.*?)\",\"(.*?)\".*?\\);";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(userNode.getText());
		
		if (!matcher.find())
		{
			System.err.print("Error! 提取评论失败!");
			return null;
		}
		
		String name = matcher.group(1);
		String url = matcher.group(2);
		String email = url;
		if (url.contains("@")) url = "";
		
		TagNode contentNode = commentNode.findElementByAttValue("class", "cnt", true, true);
		
		TagNode dateNode = contentNode.findElementByAttValue("class", "date", true, true);
		String date = dateNode.getText().toString().replaceAll("[|回复]", "");
		System.out.println(dateNode.getText());
		System.out.println("***" + date);
		
		contentNode = contentNode.findElementByAttValue("class", "desc", true, true);
		String content = contentNode.getText().toString();
		
		return new Comment(this.commentId++, name, date, url, email, content);
	}
	
	public String formatDate(String dateString)
	{
		/***
		 * 经过导入和导出测试，Wordpress对日期和时间的各种形式极度兼容， 所以不经过处理，直接保持原样就行了，时间最多会有8小时内的误差，这是可以容忍的 当然，如果完善这个方法，应该可以做到更精确
		 * 
		 * 百度hi的时间格式有 2005-11-30 2005/11/30 2005年11月30日 2005年11月30日 星期三 18:50 6:50 P.M. 下午 6:50
		 */
		//		SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd HH:mm");
		//		dateString = dateString.replaceAll("[年月日星期一二三四五六]", "");
		//		
		//		System.out.println(dateString);
		//		try
		//		{
		//			Date date = df.parse(dateString);
		//			return date;
		//		}
		//		catch (ParseException e)
		//		{
		//			System.out.println("Date format error!");
		//			e.printStackTrace();
		//		}
		
		return dateString;
	}
	
	public void convert()
	{
		nextUrl = getFirstUrl();
		while (nextUrl != null)
		{
			System.out.println("===============================================");
			blog.add(getDiary(this.baiduHi + nextUrl));
		}
		
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
		String fileName = "wordpress " + df.format(new Date()) + ".xml";
		
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("rss");
		
		root.addAttribute("version", "2.0");
		root.addNamespace("excerpt", "http://wordpress.org/export/1.0/excerpt/");
		root.addNamespace("content", "http://purl.org/rss/1.0/modules/content/");
		root.addNamespace("wfw", "http://wellformedweb.org/CommentAPI/");
		root.addNamespace("dc", "http://purl.org/dc/elements/1.1/");
		root.addNamespace("wp", "http://wordpress.org/export/1.0/");
		
		Element channel = root.addElement("channel");
		
		for (Diary diary : blog)
		{
			channel.add(diary.toXml());
		}
		
		try
		{
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("utf-8");
			format.setExpandEmptyElements(true);
			format.setIndentSize(4);
			format.setTrimText(true);
			
			XMLWriter writer = new XMLWriter(new FileWriter(fileName), format);
			writer.write(document);
			writer.close();
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws MalformedURLException, IOException, ParseException
	{
		if (args.length != 1)
		{
			System.out.println("Parameters Error!");
			return;
		}
		
		String blogName = args[0];
		new HI2WP(blogName).convert();
	}
}
